package com.love.marriage.eventRegistrationInfo.service.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.love.marriage.common.enums.DefaultAmountTypeEnum;
import com.love.marriage.common.enums.ResultEnum;
import com.love.marriage.common.enums.TransactionType;
import com.love.marriage.common.exceptions.SystemException;
import com.love.marriage.common.vo.SecurityUser;
import com.love.marriage.config.DefaultAmountConfig;
import com.love.marriage.defaultAmountConfig.service.DefaultAmountConfigService;
import com.love.marriage.defaultAmountConfig.vo.DefaultAmountConfigVo;
import com.love.marriage.eventInfo.service.EventInfoService;
import com.love.marriage.eventInfo.vo.EventInfoVo;
import com.love.marriage.eventRegistrationInfo.entity.EventRegistrationInfo;
import com.love.marriage.eventRegistrationInfo.mapper.EventRegistrationInfoMapper;
import com.love.marriage.eventRegistrationInfo.service.EventRegistrationInfoService;
import com.love.marriage.eventRegistrationInfo.vo.EventRegistrationInfoExportVo;
import com.love.marriage.eventRegistrationInfo.vo.EventRegistrationInfoVo;
import com.love.marriage.identityVerification.vo.IdentityVerificationVo;
import com.love.marriage.userActivityInfo.service.UserActivityInfoService;
import com.love.marriage.userActivityInfo.vo.UserActivityInfoVo;
import com.love.marriage.userBalanceInfo.service.UserBalanceInfoService;
import com.love.marriage.userBalanceInfo.vo.UserBalanceInfoAddVo;
import com.love.marriage.userBalanceInfo.vo.UserBalanceInfoVo;
import com.love.marriage.userPartnerPreferences.mapper.UserPartnerPreferencesMapper;
import com.love.marriage.userPartnerPreferences.vo.UserPartnerPreferencesVo;
import com.love.marriage.userProfileInfo.vo.UserProfileInfoVo;
import com.love.marriage.utils.StringUtils;
import com.love.marriage.utils.UserUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * description:  活动报名表服务实现类
 * author:       alex
 * createDate:   2024-10-15 04:29:12
 * version:      1.0.0
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class EventRegistrationInfoServiceImp extends ServiceImpl<EventRegistrationInfoMapper, EventRegistrationInfo> implements EventRegistrationInfoService {

    private final EventRegistrationInfoMapper eventRegistrationInfoMapper;

    private final UserBalanceInfoService userBalanceInfoService;

    private final DefaultAmountConfig defaultAmountConfig;

    private final DefaultAmountConfigService defaultAmountConfigService;

    private final UserActivityInfoService userActivityInfoService;

    private final EventInfoService eventInfoService;

    private final UserPartnerPreferencesMapper userPartnerPreferencesMapper;

    @Override
    public Page<EventRegistrationInfoVo> getPage(Long pageNum, Long pageSize, EventRegistrationInfoVo eventRegistrationInfoVo) {
        Page<EventRegistrationInfoVo> page = new Page<>(pageNum == null ? 1 : pageNum, pageSize == null ? 10 : pageSize);
        return eventRegistrationInfoMapper.getPage(page, eventRegistrationInfoVo);
    }

    @Override
    public List<EventRegistrationInfoVo> getList(EventRegistrationInfoVo eventRegistrationInfoVo) {
        return eventRegistrationInfoMapper.getList(eventRegistrationInfoVo);
    }

    @Override
    public EventRegistrationInfoVo queryEventRegistrationInfo(Long id) {
        return eventRegistrationInfoMapper.queryEventRegistrationInfo(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public EventRegistrationInfoVo addEventRegistrationInfo(EventRegistrationInfoVo eventRegistrationInfoVo) throws Exception {
        if (eventRegistrationInfoVo.getPaymentAmount() != null && BigDecimal.ZERO.compareTo(eventRegistrationInfoVo.getPaymentAmount()) > 0) {
            throw new Exception("支付金额不能小于0");
        }
        SecurityUser loginUser = UserUtils.getLoginUser();
        if (loginUser == null) {
            throw new SystemException(ResultEnum.USER_NO_LOGIN);
        }
        EventInfoVo eventInfoVo = eventInfoService.queryEventInfo(eventRegistrationInfoVo.getEventId());
        if (eventInfoVo == null) {
            throw new Exception("活动不存在！");
        }
        // 如果存在则提示已报名
        LambdaQueryWrapper<EventRegistrationInfo> query = Wrappers.<EventRegistrationInfo>lambdaQuery().eq(EventRegistrationInfo::getEventId, eventRegistrationInfoVo.getEventId())
                .eq(EventRegistrationInfo::getUserId, eventRegistrationInfoVo.getUserId())
                .eq(EventRegistrationInfo::getDeleteFlag, 0);
        EventRegistrationInfo db = this.getOne(query);
        if (db != null) {
            throw new SystemException(ResultEnum.EVENT_ALREADY_REGISTERED);
        }
        // 开始之前之前的一天的23:59为报名截止日期
        log.info("开始时间：{}, kaishi:{}", eventInfoVo.getStartTime(), eventInfoVo.getStartTime().minusDays(1).withHour(23).withMinute(59));
        if (eventInfoVo.getStartTime().minusDays(1).withHour(23).withMinute(59).withSecond(59).isBefore(LocalDateTime.now())) {
            throw new Exception("活动已结束报名！");
        }
        // 校验报名人数是否超出设置
        if (eventInfoVo.getParticipantsCount() != null && eventInfoVo.getParticipantsCount() <= eventInfoVo.getRegistrationCount()) {
            throw new SystemException(ResultEnum.EVENT_MAX_REGISTERED);
        }
        UserActivityInfoVo joinEvent = userActivityInfoService.queryUserActivityInfoByUser(eventRegistrationInfoVo.getUserId());
        if (joinEvent == null) {
            throw new SystemException(ResultEnum.USER_NOT_PROFILE_COMPLETE.getCode(), "请完善个人信息");
        }
//        UserProfileInfoVo userProfileInfoVo = userProfileInfoService.queryUserProfileInfoByUserId(eventRegistrationInfoVo.getUserId());
//        if (userProfileInfoVo == null) {
//            throw new SystemException(ResultEnum.USER_NOT_PROFILE_COMPLETE);
//        }
        UserBalanceInfoVo userBalanceInfoVo = userBalanceInfoService.queryUserBalanceInfoByUserId(eventRegistrationInfoVo.getUserId());
        DefaultAmountConfigVo defaultAmountConfigVo = defaultAmountConfigService.queryDefaultAmountConfigByCode(DefaultAmountTypeEnum.JOIN_EVENT.getCode());
        BigDecimal paymentAmount;
        // 如果报名金额不为空则使用报名金额，否则查看默认配置表中是否有值，最后查询配置表中配置金额
        if (eventRegistrationInfoVo.getPaymentAmount() != null) {
            paymentAmount = eventRegistrationInfoVo.getPaymentAmount();
        } else if (defaultAmountConfigVo != null) {
            paymentAmount = defaultAmountConfigVo.getAmount();
        } else {
            paymentAmount = defaultAmountConfig.getEvent();
        }
        if (BigDecimal.ZERO.compareTo(paymentAmount) < 0 && (userBalanceInfoVo == null ||
                userBalanceInfoVo.getBalance().compareTo(paymentAmount) < 0)) {
            throw new SystemException(ResultEnum.USER_NO_ENOUGH_BALANCE);
        }
        if (eventRegistrationInfoVo.getRegistrationTime() == null) {
            eventRegistrationInfoVo.setRegistrationTime(LocalDateTime.now());
        }
        eventRegistrationInfoVo.setPaymentAmount(paymentAmount);
        eventRegistrationInfoVo.setPaymentStatus(true);
        EventRegistrationInfo eventRegistrationInfo = new EventRegistrationInfo();
        BeanUtils.copyProperties(eventRegistrationInfoVo, eventRegistrationInfo);
        eventRegistrationInfoMapper.insert(eventRegistrationInfo);
        EventRegistrationInfoVo res = new EventRegistrationInfoVo();
        BeanUtils.copyProperties(eventRegistrationInfo, res);
        UserBalanceInfoAddVo userBalanceInfoAddVo = new UserBalanceInfoAddVo();
        userBalanceInfoAddVo.setUserId(eventRegistrationInfoVo.getUserId());
        userBalanceInfoAddVo.setAmount(paymentAmount);
        if (BigDecimal.ZERO.compareTo(paymentAmount) < 0) {
            userBalanceInfoService.reduceAmount(userBalanceInfoAddVo, eventRegistrationInfo.getId(), TransactionType.JOIN_EVENT.getCode(), "报名活动");
        }
        return res;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public EventRegistrationInfoVo addEventRegistrationInfoBack(EventRegistrationInfoVo eventRegistrationInfoVo) throws Exception {
        EventInfoVo eventInfoVo = eventInfoService.queryEventInfo(eventRegistrationInfoVo.getEventId());
        if (eventInfoVo == null) {
            throw new Exception("活动不存在！");
        }
        // 如果存在则提示已报名
        LambdaQueryWrapper<EventRegistrationInfo> query = Wrappers.<EventRegistrationInfo>lambdaQuery().eq(EventRegistrationInfo::getEventId, eventRegistrationInfoVo.getEventId())
                .eq(EventRegistrationInfo::getUserId, eventRegistrationInfoVo.getUserId())
                .eq(EventRegistrationInfo::getDeleteFlag, 0);
        EventRegistrationInfo db = this.getOne(query);
        if (db != null) {
            throw new SystemException(ResultEnum.EVENT_ALREADY_REGISTERED);
        }
        // 开始之前之前的一天的23:59为报名截止日期
        log.info("开始时间：{}, kaishi:{}", eventInfoVo.getStartTime(), eventInfoVo.getStartTime().minusDays(1).withHour(23).withMinute(59));
        if (eventInfoVo.getStartTime().minusDays(1).withHour(23).withMinute(59).withSecond(59).isBefore(LocalDateTime.now())) {
            throw new Exception("活动已结束报名！");
        }
        // 校验报名人数是否超出设置
        if (eventInfoVo.getParticipantsCount() != null && eventInfoVo.getParticipantsCount() <= eventInfoVo.getRegistrationCount()) {
            throw new SystemException(ResultEnum.EVENT_MAX_REGISTERED);
        }
        UserActivityInfoVo joinEvent = userActivityInfoService.queryUserActivityInfoByUser(eventRegistrationInfoVo.getUserId());
        if (joinEvent == null) {
            throw new SystemException(ResultEnum.USER_NOT_PROFILE_COMPLETE.getCode(), "请完善个人信息");
        }
        if (eventRegistrationInfoVo.getRegistrationTime() == null) {
            eventRegistrationInfoVo.setRegistrationTime(LocalDateTime.now());
        }
        eventRegistrationInfoVo.setPaymentAmount(eventRegistrationInfoVo.getPaymentAmount());
        eventRegistrationInfoVo.setPaymentStatus(true);
        EventRegistrationInfo eventRegistrationInfo = new EventRegistrationInfo();
        BeanUtils.copyProperties(eventRegistrationInfoVo, eventRegistrationInfo);
        eventRegistrationInfoMapper.insert(eventRegistrationInfo);
        EventRegistrationInfoVo res = new EventRegistrationInfoVo();
        BeanUtils.copyProperties(eventRegistrationInfo, res);
        return res;
    }

    @Override
    public EventRegistrationInfoVo updateEventRegistrationInfo(EventRegistrationInfoVo eventRegistrationInfoVo) {
        EventRegistrationInfo eventRegistrationInfo = new EventRegistrationInfo();
        BeanUtils.copyProperties(eventRegistrationInfoVo, eventRegistrationInfo);
        eventRegistrationInfoMapper.updateById(eventRegistrationInfo);
        return eventRegistrationInfoVo;
    }

    @Override
    public Boolean deleteEventRegistrationInfo(String ids) {
        if (StringUtils.isEmpty(ids)) {
            return true;
        }
        List<String> idArr = Arrays.asList(ids.split(","));
        eventRegistrationInfoMapper.deleteBatchIds(idArr);
        return true;
    }

    @Override
    public void exportEventRegistrationInfo(EventRegistrationInfoVo eventRegistrationInfoVo, HttpServletResponse response) throws Exception {
        List<EventRegistrationInfoVo> list = eventRegistrationInfoMapper.getList(eventRegistrationInfoVo);
        List<EventRegistrationInfoExportVo> res = list.stream().map(item -> {
            EventRegistrationInfoExportVo datingRegistrationInfoExportVo = new EventRegistrationInfoExportVo();
            datingRegistrationInfoExportVo.setEventId(item.getEventId());
            if (item.getEventInfoVo() != null) {
                datingRegistrationInfoExportVo.setTitle(item.getEventInfoVo().getTitle());
                datingRegistrationInfoExportVo.setStartTime(item.getEventInfoVo().getStartTime());
            }
            if (item.getUserInfoVo() != null) {
                datingRegistrationInfoExportVo.setCode(item.getUserInfoVo().getCode());
                datingRegistrationInfoExportVo.setPhone(item.getUserInfoVo().getPhone());
            }
            if (item.getUserProfileInfoVo() != null) {
                UserProfileInfoVo userProfileInfoVo = item.getUserProfileInfoVo();
                datingRegistrationInfoExportVo.setNickname(userProfileInfoVo.getNickname());
                datingRegistrationInfoExportVo.setGender(userProfileInfoVo.getGender());
                if (userProfileInfoVo.getBirthYearMonth() != null) {
                    int age = Period.between(userProfileInfoVo.getBirthYearMonth(), LocalDate.now()).getYears();
                    datingRegistrationInfoExportVo.setAge(age);
                }
                datingRegistrationInfoExportVo.setWeight(userProfileInfoVo.getWeight());
                datingRegistrationInfoExportVo.setHeight(userProfileInfoVo.getHeight());
                datingRegistrationInfoExportVo.setProfessionName(userProfileInfoVo.getProfessionName());
                datingRegistrationInfoExportVo.setIncomeStatusName(userProfileInfoVo.getIncomeStatusName());
                String region = "";
                if (userProfileInfoVo.getProvinceName() != null) {
                    region += userProfileInfoVo.getProvinceName() + "/";
                }
                if (userProfileInfoVo.getCityName() != null) {
                    region += userProfileInfoVo.getCityName() + "/";
                }
                if (userProfileInfoVo.getDistrictName() != null) {
                    region += userProfileInfoVo.getCityName() + "/";
                }
                if (region.endsWith("/")) {
                    region = region.substring(0, region.length() - 1);
                }
                datingRegistrationInfoExportVo.setRegion(region);
            }
            if (item.getIdentityVerificationVo() != null) {
                IdentityVerificationVo identityVerificationVo = item.getIdentityVerificationVo();
                datingRegistrationInfoExportVo.setName(identityVerificationVo.getName());
                datingRegistrationInfoExportVo.setIdCardNumber(identityVerificationVo.getIdCardNumber());
            }
            // 追加：按用户ID关联导出“择偶要求”
            if (item.getUserId() != null) {
                UserPartnerPreferencesVo pref = userPartnerPreferencesMapper.queryUserPartnerPreferencesByUserId(item.getUserId());
                if (pref != null) {
                    datingRegistrationInfoExportVo.setPrefAgeFrom(pref.getAgeFrom());
                    datingRegistrationInfoExportVo.setPrefAgeTo(pref.getAgeTo());
                    datingRegistrationInfoExportVo.setPrefHeightFrom(pref.getHeightFrom());
                    datingRegistrationInfoExportVo.setPrefHeightTo(pref.getHeightTo());
                    datingRegistrationInfoExportVo.setPrefWeightFrom(pref.getWeightFrom());
                    datingRegistrationInfoExportVo.setPrefWeightTo(pref.getWeightTo());
                    datingRegistrationInfoExportVo.setPrefEducationLevel(pref.getEducationLevelName());
                    datingRegistrationInfoExportVo.setPrefProfession(pref.getProfessionName());
                    datingRegistrationInfoExportVo.setPrefIncomeRange(pref.getIncomeRangeName());
                    datingRegistrationInfoExportVo.setPrefHousingCarStatus(pref.getHousingCarStatusName());
                    datingRegistrationInfoExportVo.setPrefMaritalStatus(pref.getMaritalStatusName());

                    String prefRegion = "";
                    if (pref.getProvinceName() != null) {
                        prefRegion += pref.getProvinceName() + "/";
                    }
                    if (pref.getCityName() != null) {
                        prefRegion += pref.getCityName() + "/";
                    }
                    if (pref.getDistrictName() != null) {
                        prefRegion += pref.getDistrictName() + "/";
                    }
                    if (prefRegion.endsWith("/")) {
                        prefRegion = prefRegion.substring(0, prefRegion.length() - 1);
                    }
                    datingRegistrationInfoExportVo.setPrefProvinceName(pref.getProvinceName());
                    datingRegistrationInfoExportVo.setPrefCityName(pref.getCityName());
                    datingRegistrationInfoExportVo.setPrefDistrictName(pref.getDistrictName());
                    datingRegistrationInfoExportVo.setPrefRegion(prefRegion);
                }
            }
            datingRegistrationInfoExportVo.setRegistrationTime(item.getRegistrationTime());
            datingRegistrationInfoExportVo.setPaymentAmount(item.getPaymentAmount());
            return datingRegistrationInfoExportVo;
        }).collect(Collectors.toList());
        exportDatingRegistrationData(res, response);
    }

    public void exportDatingRegistrationData(List<EventRegistrationInfoExportVo> registrationInfoVoList, HttpServletResponse response) throws Exception {
        // 设置导出参数
        ExportParams exportParams = new ExportParams("报名名单信息", "报名名单");

        // 生成 Excel
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, EventRegistrationInfoExportVo.class, registrationInfoVoList);

        // 设置响应头
        // 设置返回类型为excel
        response.setContentType("application/vnd.ms-excel; charset=UTF-8");
        // 设置返回文件名为filename.xls
        response.setHeader("Content-Disposition", "filename.xls");
        // 请求或响应消息不能走缓存
        response.setHeader("Cache-Control", "no-cache");
        // 将Content-Disposition暴露出去，这样就可以用过JS获取到了
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        // 将 Excel 写入响应输出流并刷新缓冲区
        workbook.write(response.getOutputStream());
        response.flushBuffer(); // 确保数据完全写出
        workbook.close();
    }
}
